#include "Managers/ComponentsManager.h"
#include "Managers/GameManager.h"

#include "Utils/Utils.h"
#include "Terrain/Terrain.h"
#include "Game/EntityData.hpp"
#include "Log.h"

#include "Components/Component.hpp"
#include "Components/ComponentCreature.h"
#include "Components/ComponentHumanModel.h"
#include "Components/ComponentCreatureModel.h"
#include "Components/ComponentLocomotion.h"
#include "Components/ComponentPlayer.h"
#include "Components/ComponentHealth.h"
#include "Components/ComponentSleep.h"
#include "Components/ComponentClothing.h"
#include "Components/ComponentFlu.h"
#include "Components/ComponentInventory.h"
#include "Components/ComponentSpawn.h"
#include "Components/ComponentIntro.h"
#include "Components/ComponentSickness.h"
#include "Components/ComponentBody.h"
#include "Components/ComponentFurnitureInventory.h"
#include "Components/ComponentOnFire.h"
#include "Components/ComponentCreativeInventory.h"
#include "Components/ComponentCraftingTable.h"
#include "Components/ComponentVitalStats.h"
#include "Components/ComponentMiner.h"
#include "Components/ComponentAttacker.h"
#include "Components/ComponentLevel.h"
#include "Components/ComponentBlockEntity.h"
#include "Components/ComponentChest.h"
#include "Components/ComponentFurnace.h"
#include "Components/ComponentDamage.h"
#include "Components/ComponentCreatureSounds.h"
#include "Components/ComponentAntiCheat.h"


#include "GameThreadPool.hpp"
#include "GameSingleton.h"
#include "GameRegistry.hpp"


namespace PocketSurvival
{
    ComponentsManager::ComponentsManager() {}
    ComponentsManager::~ComponentsManager() {}

    void ComponentsManager::loadGame()
    {
        emplaceComponent<ComponentCreatureModel>();
        emplaceComponent<ComponentCreature>();
        emplaceComponent<ComponentHumanModel>();
        emplaceComponent<ComponentPlayer>();
        emplaceComponent<ComponentLocomotion>();
        emplaceComponent<ComponentHealth>();
        emplaceComponent<ComponentSleep>();
        emplaceComponent<ComponentClothing>();
        emplaceComponent<ComponentFlu>();
        emplaceComponent<ComponentInventory>();
        emplaceComponent<ComponentSpawn>();
        emplaceComponent<ComponentIntro>();
        emplaceComponent<ComponentSickness>();
        emplaceComponent<ComponentBody>();
        emplaceComponent<ComponentFurnitureInventory>();
        emplaceComponent<ComponentOnFire>();
        emplaceComponent<ComponentCreativeInventory>();
        emplaceComponent<ComponentCraftingTable>();
        emplaceComponent<ComponentVitalStats>();
        emplaceComponent<ComponentMiner>();
        emplaceComponent<ComponentAttacker>();
        emplaceComponent<ComponentLevel>();
        emplaceComponent<ComponentBlockEntity>();
        emplaceComponent<ComponentChest>();
        emplaceComponent<ComponentFurnace>();
        emplaceComponent<ComponentDamage>();
        emplaceComponent<ComponentCreatureSounds>();
        
        emplaceComponent<ComponentAntiCheat>();
    }

    void ComponentsManager::update(float dt)
    {
        auto view = GameSingleton::gameRegistry->view<TableComponent*>();
        for (entt::entity entity : view)
        {
            TableComponent* table = view.get<TableComponent*>(entity);
            
            GameSingleton::gameThreadPool->push_task(
                [table, dt]
                {
                    for (auto it = table->m_componentMap.begin(); it != table->m_componentMap.end(); ++it)
                    {
                        it->second->update(dt);
                    }
                });
        }
    }


    void ComponentsManager::entityRemoveComponents(entt::entity entity)
    {
        // 没有实体在创建时都会添加EntityData和组件数据，这里需要把这些内存释放掉
        EntityData *entityData = GameSingleton::gameRegistry->get<EntityData *>(entity);
        delete entityData;
        TableComponent *table = GameSingleton::gameRegistry->get<TableComponent *>(entity);
        for (auto it = table->m_componentMap.begin(); it != table->m_componentMap.end(); ++it)
        {
            delete it->second;
        }
        delete table;
    }


    void ComponentsManager::entityAddComponents(entt::entity entity ,const nlohmann::json &jsonData)
    {
        auto tableCom = GameSingleton::gameRegistry->emplace<TableComponent *>(entity, new TableComponent);
        auto entityData = GameSingleton::gameRegistry->emplace<EntityData*>(entity, new EntityData);

        entityData->ObjectGuid = jsonData["ObjectGuid"].get<std::string>();
        entityData->ObjectName = jsonData["ObjectName"].get<std::string>();

        const nlohmann::json &componentJson = jsonData["Components"];

        for(const auto &jsonItem : componentJson.items())
        {
            auto it = m_baseComponentMap.find(jsonItem.key());
            if(it != m_baseComponentMap.end())
            {
                Component *component = GameSingleton::gameRegistry->storage<Component*>(it->second.hashValue).emplace(entity, it->second.createFunction());

                tableCom->m_componentMap.emplace(it->second.hashValue, component);
            }
            else
            {
                Log::Warn(fmt::format("实体 {}，需要的组件 {} 不存在", entityData->ObjectName, jsonItem.key()));
            }
        }

        nlohmann::json nullJson = {};
        for(auto &pair : tableCom->m_componentMap)
        {
            pair.second->entity = entity;
            auto it = componentJson.find(pair.second->getName());
            if(it != componentJson.end())
            {
                pair.second->load(*it);
            }
            else
            {
                pair.second->load(nullJson);
                Log::Warn(fmt::format("没有找到实体组件数据 {}", pair.second->getName()));
            }
        }
    }

    void ComponentsManager::saveComponents(entt::entity entity, nlohmann::json &jsonData)
    {
        TableComponent *tableCom = GameSingleton::gameRegistry->get<TableComponent*>(entity);
        for (auto &pair : tableCom->m_componentMap)
        {
            nlohmann::json comJson;
            pair.second->save(comJson);
            if(comJson.is_null() == false)
            {
                jsonData[pair.second->getName()] = comJson;
            }
        }
    }

    void ComponentsManager::saveEntityToMsgJson(entt::entity entity, nlohmann::json &jsonData)
    {
        TableComponent *tableCom = GameSingleton::gameRegistry->get<TableComponent*>(entity);
        EntityData *entityData = GameSingleton::gameRegistry->get<EntityData*>(entity);

        MSG_VALUE_SET(jsonData, "Id", "int", (int32_t)entity);
        MSG_VALUE_SET(jsonData, "Guid", "System.Guid", entityData->ObjectGuid);
        MSG_VALUE_SET(jsonData, "Name", "string", entityData->ObjectName);

        nlohmann::json overrideJson;
        for (auto &pair : tableCom->m_componentMap)
        {
            nlohmann::json comMsgJson;
            pair.second->saveToMsgJson(comMsgJson);
            if(comMsgJson.is_null() == false)
            {
                overrideJson[pair.second->getName()] = comMsgJson;
            }
        }

        jsonData["Overrides"] = overrideJson;
    }
    
    
} // namespace PocketSurvival
